package model;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;

public class Monster
{
	public GameBoard gameBoard;
	public GameTile currentLocation, playerLocation;
	public ArrayList<GameTile> allCorners;
	public int delay = 250;

	public Monster()
	{
		allCorners = new ArrayList<GameTile>();
		gameBoard = new GameBoard();
	}

	public void SeekAndDestroy()
	{
		try
		{
			while (currentLocation.getxCoord() != playerLocation.getxCoord()
					|| currentLocation.getyCoord() != playerLocation
							.getyCoord())
			{

				findNearestWayPoint();
				moveTowardsPlayer();
			}
		}
		catch (PlayerEatenException e)
		{
			System.out.println("Player Eaten! NOM NOM NOM");
		}
	}

	public void findNearestWayPoint() throws PlayerEatenException
	{
		int cornerX = 0, cornerY = 0;
		// check if the tile it is on is a corner first
		if (isOnWayPoint(currentLocation.getxCoord(),
				currentLocation.getyCoord()))
		{
			return;
		}
		else
		{
			// Monster is on a "column" needs to move laterally.
			if (currentLocation.getyCoord() == 0
					|| currentLocation.getyCoord() == 4
					|| currentLocation.getyCoord() == 8)
			{// player is left of monster
				if (playerLocation.getxCoord() < currentLocation.getxCoord())
				{
					// move monster left
					moveMonster(-1, 0);
					findNearestWayPoint();
				}
				else if (playerLocation.getxCoord() > currentLocation
						.getxCoord())
				{
					moveMonster(1, 0);
					findNearestWayPoint();
				}
				else
				{
					// case where player could be directly over or under monster
					// thus it chooses the direction
					if ((int) Math.random() % 2 == 0)
					{// left, right
						moveMonster(-1, 0);
						findNearestWayPoint();
					}
					else
					{
						moveMonster(1, 0);
						findNearestWayPoint();
					}
				}
			}
			else
			{
				// needs to move vertically
				if (playerLocation.getyCoord() < currentLocation.getyCoord())
				{
					// move monster left
					moveMonster(0, -1);
					findNearestWayPoint();
				}
				else if (playerLocation.getyCoord() > currentLocation
						.getyCoord())
				{
					moveMonster(0, 1);
					findNearestWayPoint();
				}
				else
				{
					// case where player could be directly over or under monster
					// thus it chooses the direction
					if ((int) Math.random() % 2 == 0)
					{// left, right
						moveMonster(0, -1);
						findNearestWayPoint();
					}
					else
					{
						moveMonster(0, 1);
						findNearestWayPoint();
					}
				}
			}

		}

	}

	public ArrayList<GameTile> findPlayer()
	{
		ArrayList<GameTile> playerLocations = new ArrayList<GameTile>(4);

		for (Enumeration<GameTile> en = gameBoard.getBoard().elements(); en
				.hasMoreElements();)
		{
			GameTile derp = en.nextElement();
			if (derp.isOccupied())
			{
				playerLocations.add(derp);
			}
		}

		return playerLocations;
	}

	public void moveTowardsPlayer() throws PlayerEatenException
	{
		if (isFarthestAxisY())
		{
			// dir is up or down
			int dir;
			// close in on Y Axis
			if (currentLocation.getyCoord() < playerLocation.getyCoord())
			{
				dir = 1;
			}
			else
			{
				dir = -1;
			}
			for (int i = 0; i < 3; i++)
			{
				moveMonster(0, dir);
			}
		}
		else
		{
			int dir;
			// close in on Y Axis
			if (currentLocation.getxCoord() < playerLocation.getxCoord())
			{
				dir = 1;
			}
			else
			{
				dir = -1;
			}
			for (int i = 0; i < 3; i++)
			{
				moveMonster(dir, 0);
			}
		}
	}

	/**
	 * Determines which on which axis the player is farthest from the monster, X
	 * or Y
	 * 
	 * @return
	 */
	public boolean isFarthestAxisY()
	{
		int xDist, yDist;

		xDist = Math.abs(currentLocation.getxCoord()
				- playerLocation.getxCoord());
		yDist = Math.abs(currentLocation.getyCoord()
				- playerLocation.getyCoord());

		if (yDist >= xDist)
		{
			return true;
		}

		return false;
	}

	public void setWayPoints()
	{
		allCorners.add(gameBoard.getTilebyCoordinate(0, 0));
		allCorners.add(gameBoard.getTilebyCoordinate(0, 4));
		allCorners.add(gameBoard.getTilebyCoordinate(0, 8));
		allCorners.add(gameBoard.getTilebyCoordinate(4, 0));
		allCorners.add(gameBoard.getTilebyCoordinate(4, 4));
		allCorners.add(gameBoard.getTilebyCoordinate(4, 8));
		allCorners.add(gameBoard.getTilebyCoordinate(8, 0));
		allCorners.add(gameBoard.getTilebyCoordinate(8, 4));
		allCorners.add(gameBoard.getTilebyCoordinate(8, 8));

	}

	/**
	 * changes the monsters position, can only move one direction at a time,
	 * thus if one argument is not zero, it will do nothing
	 * 
	 * @param x
	 *            integer to change position on x axis positive integers move
	 *            right, negative moves left
	 * @param y
	 *            integer to change position on y axis positive integers move
	 *            down, negative moves up
	 * @throws PlayerEatenException
	 */
	public void moveMonster(int x, int y) throws PlayerEatenException
	{
		if (x != 0 && y != 0)
		{
			// invalid move, madp only allows monster to move in one direction
		}
		else
		{
			currentLocation.setOccupiedByMonster(false);
			currentLocation = gameBoard.getTilebyCoordinate(
					currentLocation.getxCoord() + x,
					currentLocation.getyCoord() + y);
			currentLocation.setOccupiedByMonster(true);
		}
		try
		{
			Thread.sleep(delay);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		System.out.println("Current Location is " + currentLocation.getxCoord()
				+ "," + currentLocation.getyCoord());
		if (isPlayerEaten())
		{
			throw new PlayerEatenException();
		}
	}

	public boolean isOnWayPoint(int x, int y)
	{
		boolean xtrue = false, ytrue = false;

		// hacky cheap way of determining corner
		if (x == 0 || x == 4 || x == 8)
		{
			xtrue = true;
		}
		if (y == 0 || y == 4 || y == 8)
		{
			ytrue = true;
		}

		if (xtrue && ytrue)
		{
			return true;
		}
		return false;
	}

	public boolean isPlayerEaten()
	{
		if (currentLocation.getxCoord() == playerLocation.getxCoord()
				&& currentLocation.getyCoord() == currentLocation.getyCoord())
		{
			return true;
		}
		return false;
	}

	public void generateSampleBoard()
	{
		for (int i = 0; i < 9; i++)
		{
			for (int j = 0; j < 9; j++)
			{
				boolean isStage = true;
				switch (i)
				{
				case 0:
					break;
				case 1:
					if (j != 0 && j != 4 && j != 8)
						isStage = false;
					break;
				case 2:
					if (j != 0 && j != 4 && j != 8)
						isStage = false;
					break;
				case 3:
					if (j != 0 && j != 4 && j != 8)
						isStage = false;
					break;
				case 4:
					break;
				case 5:
					if (j != 0 && j != 4 && j != 8)
						isStage = false;
					break;
				case 6:
					if (j != 0 && j != 4 && j != 8)
						isStage = false;
					break;
				case 7:
					if (j != 0 && j != 4 && j != 8)
						isStage = false;
					break;
				case 8:
					break;
				}

				if (isStage == true)
				{

					try
					{
						gameBoard.addTilebyCoordinate(new GameTile(true, false,
								i, j));
					}
					catch (Exception e)
					{
						e.printStackTrace();
					}
				}
				else
				{
					try
					{
						gameBoard.addTilebyCoordinate(new GameTile(true, false,
								i, j));
					}
					catch (Exception e)
					{
						e.printStackTrace();
					}
				}
			}
		}
		return;
	}
}